/* libstdf -- library for reading writing and manipulating STDF files and data.
   Copyright (C) 2009 Tushar Jog
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA 
*/

using System;
using System.Collections.Generic;


using U1 = System.Byte;
using U2 = System.UInt16;
using I1 = System.SByte;
using I2 = System.Int16;
using U4 = System.UInt32;
using I4 = System.Int32;
using R4 = System.Single;
using R8 = System.Double;
//using C1 = System.SByte;
using C1 = System.Char;
using B1 = System.Byte;
using N1 = System.Byte;

namespace stdf {

    public class RecordHeader {
        public RecordHeader() {
            length 	= 0;
            type 	= 0;
            subType = 0;
        }
        public RecordHeader( U1 _type, U1 _subType, U2 _len) {
            // TODO add error check for invalid type and subType
            length 	= _len;
            subType = _subType;
            type 	= _type;
        }
        public RecordHeader( RecordType recType) {
            int recInt = (int) recType;

            type = (U1) (recInt/100);
            subType = (U1) (recInt - type*100);
        }

        //public RecordHeader operator = (ref RecordType recType) {
        //}

        public RecordType getRecordType() {
            int recInt = type*100 + subType;
            RecordType recType = RecordType.Header;
            if(Enum.IsDefined(typeof(RecordType), recInt))
                recType = (RecordType) recInt;
            return recType;
        }
        public string getRecordTypeString() {
            RecordType recType = getRecordType();
            return recType.ToString();
        }
        public U2 getLength() { 
            return length;
        }

        public string ToString() {
            string text = "";
            text += getRecordTypeString() + "\t" + length.ToString() + "\t" + type.ToString() + "\t" + subType.ToString();
            return text;
        }

        public static void recordTypeToTypes( ref RecordType rec, ref U1 _type, ref U1 _subType) {
            int recInt 	= (int) rec;
            _type 		= (U1) (recInt / 100);
            _subType 	= (U1) (recInt % 100);
        }

        public U2 length;
        public U1 type;
        public U1 subType;

    }

    public abstract class Record {
        public Record() {
            recordHeader = new RecordHeader(RecordType.Header);
        }

        public abstract U2 getLength();
        public abstract void getFields(ref List< Pair<string, string> > fields);
        public abstract RecordType getRecordType();
        public string   getRecordTypeString() { return getRecordType().ToString(); }
        public override string ToString()
        {
            string sep = "\t";
            string text = "";
            List<Pair<string, string> > fields = new List<Pair<string, string>>();
            getFields(ref fields);

            text += getRecordTypeString() + "\n";
            for(int i=0; i < fields.Count; i++) {
                text += sep + fields[i].First.ToString() + ":" + sep + fields[i].Second.ToString() + "\n";
            }

            return text;
        }

        protected RecordHeader recordHeader;
    }

    public class FARRecord : Record {
        public FARRecord() {
            recordHeader = new RecordHeader(RecordType.FAR);
            cpuType = 0;
            stdfVersion = 0;

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 cpuType
            len += 1; // U1 stdfVersion

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "cpuType",	cpuType.ToString() ) );
            fields.Add( new Pair<string, string>( "stdfVersion",	stdfVersion.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.FAR; }


        public ByteOrder getByteOrder() { 			
            ByteOrder byteOrder;

            switch(cpuType) {
                case  0: byteOrder = ByteOrder.PDPEndian; break;
                case  1: byteOrder = ByteOrder.BigEndian; break;
                case  2: byteOrder = ByteOrder.LittleEndian; break;
                default: byteOrder = ByteOrder.NotDefined; break;
            };
            return byteOrder;
        }
        public U1 getCpuType() { return cpuType; }

        public U1 cpuType;
        public U1 stdfVersion;

    };


    public class ATRRecord : Record {
        public ATRRecord() {
            recordHeader = new RecordHeader(RecordType.ATR);
            modificationTime = 0;
            commandLine = new CN();

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 4; // U4 modificationTime
            len += commandLine.getLength(); // CN commandLine

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "modificationTime",	modificationTime.ToString() ) );
            fields.Add( new Pair<string, string>( "commandLine",	commandLine.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.ATR; }

        public U4 modificationTime;
        public CN commandLine;

    };

    public class BPSRecord : Record {
        public BPSRecord() {
            recordHeader = new RecordHeader(RecordType.BPS);
            sequencerName = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += sequencerName.getLength(); // CN sequencerName

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "sequencerName",	sequencerName.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.BPS; }

        public CN sequencerName;

    };




    public class DTRRecord : Record {
        public DTRRecord() {
            recordHeader = new RecordHeader(RecordType.DTR);
            textData = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += textData.getLength(); // CN textData

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "textData",	textData.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.DTR; }

        public CN textData;

    };




    public class EPSRecord : Record {
        public EPSRecord() {
            recordHeader = new RecordHeader(RecordType.EPS);

        }
        public override U2 getLength() {
            U2 len = 0;

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {

        }
        public override RecordType getRecordType() { return RecordType.EPS; }

    };


    public class FTRRecord : Record {
        public FTRRecord() {
            recordHeader = new RecordHeader(RecordType.FTR);
            testNumber             = 0;
            headNumber             = 0;
            siteNumber             = 0;
            testFlag               = 0;
            optFlag                = 0;
            cycleCount             = 0;
            relativeVectorAddress  = 0;
            repeatCount            = 0;
            numFail                = 0;
            xFailAddress           = 0;
            yFailAddress           = 0;
            vectorOffset           = 0;
            returnIcnt             = 0;
            programmedIcnt         = 0;
            patternGeneratorNumber = 0;
            returnIndexes = new List<U2>();
            returnStates  = new List<N1>();
            programmedIndexes = new List<U2>();
            programmedStates = new List<N1>();
            failPin = new DN();
            vectorName = new CN();
            timeSet = new CN();
            opCode = new CN();
            testText = new CN();
            alarmID = new CN();
            programmedText = new CN();
            resultText = new CN();
            spinMap = new DN();

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 4; // U4 testNumber
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 1; // B1 testFlag
            len += 1; // B1 optFlag
            len += 4; // U4 cycleCount
            len += 4; // U4 relativeVectorAddress
            len += 4; // U4 repeatCount
            len += 4; // U4 numFail
            len += 4; // I4 xFailAddress
            len += 4; // I4 yFailAddress
            len += 2; // I2 vectorOffset
            len += 2; // U2 returnIcnt
            len += 2; // U2 programmedIcnt
            len += 2; // U2 returnIndexes
            len += 1; // N1 returnStates
            len += 2; // U2 programmedIndexes
            len += 1; // N1 programmedStates
            len += failPin.getLength(); // DN failPin
            len += vectorName.getLength(); // CN vectorName
            len += timeSet.getLength(); // CN timeSet
            len += opCode.getLength(); // CN opCode
            len += testText.getLength(); // CN testText
            len += alarmID.getLength(); // CN alarmID
            len += programmedText.getLength(); // CN programmedText
            len += resultText.getLength(); // CN resultText
            len += 1; // U1 patternGeneratorNumber
            len += spinMap.getLength(); // DN spinMap

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "testNumber",	testNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "testFlag",	testFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "optFlag",	optFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "cycleCount",	cycleCount.ToString() ) );
            fields.Add( new Pair<string, string>( "relativeVectorAddress",	relativeVectorAddress.ToString() ) );
            fields.Add( new Pair<string, string>( "repeatCount",	repeatCount.ToString() ) );
            fields.Add( new Pair<string, string>( "numFail",	numFail.ToString() ) );
            fields.Add( new Pair<string, string>( "xFailAddress",	xFailAddress.ToString() ) );
            fields.Add( new Pair<string, string>( "yFailAddress",	yFailAddress.ToString() ) );
            fields.Add( new Pair<string, string>( "vectorOffset",	vectorOffset.ToString() ) );
            fields.Add( new Pair<string, string>( "returnIcnt",	returnIcnt.ToString() ) );
            fields.Add( new Pair<string, string>( "programmedIcnt",	programmedIcnt.ToString() ) );
            fields.Add( new Pair<string, string>( "returnIndexes",	returnIndexes.ToString() ) );
            fields.Add( new Pair<string, string>( "returnStates",	returnStates.ToString() ) );
            fields.Add( new Pair<string, string>( "programmedIndexes",	programmedIndexes.ToString() ) );
            fields.Add( new Pair<string, string>( "programmedStates",	programmedStates.ToString() ) );
            fields.Add( new Pair<string, string>( "failPin",	failPin.ToString() ) );
            fields.Add( new Pair<string, string>( "vectorName",	vectorName.ToString() ) );
            fields.Add( new Pair<string, string>( "timeSet",	timeSet.ToString() ) );
            fields.Add( new Pair<string, string>( "opCode",	opCode.ToString() ) );
            fields.Add( new Pair<string, string>( "testText",	testText.ToString() ) );
            fields.Add( new Pair<string, string>( "alarmID",	alarmID.ToString() ) );
            fields.Add( new Pair<string, string>( "programmedText",	programmedText.ToString() ) );
            fields.Add( new Pair<string, string>( "resultText",	resultText.ToString() ) );
            fields.Add( new Pair<string, string>( "patternGeneratorNumber",	patternGeneratorNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "spinMap",	spinMap.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.FTR; }

        //
        // testFlag decoding
        //
        public bool isFail()            { return ((testFlag & 0x80) > 0); }
        public bool isPass()            { return ((testFlag & 0x80) == 0); }
        public bool isAlarm()           { return ((testFlag & 0x01) > 0); }
        public bool isUnreliable()      { return ((testFlag & 0x04) > 0); }
        public bool isReliable()        { return ((testFlag & 0x04) == 0); }
        public bool isTimeout()         { return ((testFlag & 0x08) > 0); }
        public bool isExecuted()        { return ((testFlag & 0x10) == 0); }
        public bool isAborted()         { return ((testFlag & 0x20) > 0); }
        public bool isPFValid()         { return ((testFlag & 0x40) == 0); }

        //
        // optFlag decoding
        //
        public bool isCycleCountValid()             { return ((optFlag & 0x01) == 0); }
        public bool isRelativeVectorAddressValid()  { return ((optFlag & 0x02) == 0); }
        public bool isRepeatCountValid()            { return ((optFlag & 0x04) == 0); }
        public bool isNumFailValid()                { return ((optFlag & 0x08) == 0); }
        public bool isFailAddressValid()            { return ((optFlag & 0x10) == 0); }
        public bool isVectorOffsetValid()           { return ((optFlag & 0x20) == 0); }

        public U4       testNumber;
        public U1       headNumber;
        public U1       siteNumber;
        public B1       testFlag;
        public B1       optFlag;
        public U4       cycleCount;
        public U4       relativeVectorAddress;
        public U4       repeatCount;
        public U4       numFail;
        public I4       xFailAddress;
        public I4       yFailAddress;
        public I2       vectorOffset;
        public U2       returnIcnt;
        public U2       programmedIcnt;
        public List<U2> returnIndexes;
        public List<N1> returnStates;
        public List<U2> programmedIndexes;
        public List<N1> programmedStates;
        public DN       failPin;
        public CN       vectorName;
        public CN       timeSet;
        public CN       opCode;
        public CN       testText;
        public CN       alarmID;
        public CN       programmedText;
        public CN       resultText;
        public U1       patternGeneratorNumber;
        public DN       spinMap;

    };




    public class GDRRecord : Record {
        public GDRRecord() {
            recordHeader = new RecordHeader(RecordType.GDR);
            fieldCount = 0;
            genericData = new VN();

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 2; // U2 fieldCount
            len += genericData.getLength(); // VN genericData

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "fieldCount",	fieldCount.ToString() ) );
            fields.Add( new Pair<string, string>( "genericData",	genericData.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.GDR; }

        public U2 fieldCount;
        public VN genericData;

    };




    public class HBRRecord : Record {
        public HBRRecord() {
            recordHeader = new RecordHeader(RecordType.HBR);
            headNumber = 0;
            siteNumber = 0;
            hbinNumber = 0;
            hbinCount = 0;
            hbinPF = ' ';
            hbinName = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 2; // U2 hbinNumber
            len += 4; // U4 hbinCount
            len += 1; // C1 hbinPF
            len += hbinName.getLength(); // CN hbinName

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "hbinNumber",	hbinNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "hbinCount",	hbinCount.ToString() ) );
            fields.Add( new Pair<string, string>( "hbinPF",	hbinPF.ToString() ) );
            fields.Add( new Pair<string, string>( "hbinName",	hbinName.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.HBR; }

        public U1 headNumber;
        public U1 siteNumber;
        public U2 hbinNumber;
        public U4 hbinCount;
        public C1 hbinPF;
        public CN hbinName;

    };




    public class MIRRecord : Record {
        public MIRRecord() {
            recordHeader = new RecordHeader(RecordType.MIR);
            setupTime         = 0;
            startTime         = 0;
            stationNumber     = 0;
            modeCode          = ' ';
            retestCode        = ' ';
            protectionCode    = ' ';
            burninTime        = 0;
            commandModeCode   = ' ';
            lotID             = new CN();
            partType          = new CN();;
            nodeName          = new CN();
            testerType        = new CN();
            jobName           = new CN();
            jobRevision       = new CN();
            sublotID          = new CN();
            operatorName      = new CN();
            executiveType     = new CN();
            executiveVersion  = new CN();
            testCode          = new CN();
            testTemp          = new CN();
            userText          = new CN();
            auxFile           = new CN();
            packageType       = new CN();
            familyID          = new CN();
            dateCode          = new CN();
            facilityID        = new CN();
            floorID           = new CN();
            processID         = new CN();
            operatorFrequency = new CN();
            specName          = new CN();
            specVersion       = new CN();
            flowID            = new CN();
            setupID           = new CN();
            designRevision    = new CN();
            engineeringLotID  = new CN();
            romCode           = new CN();
            serialNumber      = new CN();
            supervisorName    = new CN();

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 4; // U4 setupTime
            len += 4; // U4 startTime
            len += 1; // U1 stationNumber
            len += 1; // C1 modeCode
            len += 1; // C1 retestCode
            len += 1; // C1 protectionCode
            len += 2; // U2 burninTime
            len += 1; // C1 commandModeCode
            len += lotID.getLength(); // CN lotID
            len += partType.getLength(); // CN partType
            len += nodeName.getLength(); // CN nodeName
            len += testerType.getLength(); // CN testerType
            len += jobName.getLength(); // CN jobName
            len += jobRevision.getLength(); // CN jobRevision
            len += sublotID.getLength(); // CN sublotID
            len += operatorName.getLength(); // CN operatorName
            len += executiveType.getLength(); // CN executiveType
            len += executiveVersion.getLength(); // CN executiveVersion
            len += testCode.getLength(); // CN testCode
            len += testTemp.getLength(); // CN testTemp
            len += userText.getLength(); // CN userText
            len += auxFile.getLength(); // CN auxFile
            len += packageType.getLength(); // CN packageType
            len += familyID.getLength(); // CN familyID
            len += dateCode.getLength(); // CN dateCode
            len += facilityID.getLength(); // CN facilityID
            len += floorID.getLength(); // CN floorID
            len += processID.getLength(); // CN processID
            len += operatorFrequency.getLength(); // CN operatorFrequency
            len += specName.getLength(); // CN specName
            len += specVersion.getLength(); // CN specVersion
            len += flowID.getLength(); // CN flowID
            len += setupID.getLength(); // CN setupID
            len += designRevision.getLength(); // CN designRevision
            len += engineeringLotID.getLength(); // CN engineeringLotID
            len += romCode.getLength(); // CN romCode
            len += serialNumber.getLength(); // CN serialNumber
            len += supervisorName.getLength(); // CN supervisorName

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "setupTime",	setupTime.ToString() ) );
            fields.Add( new Pair<string, string>( "startTime",	startTime.ToString() ) );
            fields.Add( new Pair<string, string>( "stationNumber",	stationNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "modeCode",	modeCode.ToString() ) );
            fields.Add( new Pair<string, string>( "retestCode",	retestCode.ToString() ) );
            fields.Add( new Pair<string, string>( "protectionCode",	protectionCode.ToString() ) );
            fields.Add( new Pair<string, string>( "burninTime",	burninTime.ToString() ) );
            fields.Add( new Pair<string, string>( "commandModeCode",	commandModeCode.ToString() ) );
            fields.Add( new Pair<string, string>( "lotID",	lotID.ToString() ) );
            fields.Add( new Pair<string, string>( "partType",	partType.ToString() ) );
            fields.Add( new Pair<string, string>( "nodeName",	nodeName.ToString() ) );
            fields.Add( new Pair<string, string>( "testerType",	testerType.ToString() ) );
            fields.Add( new Pair<string, string>( "jobName",	jobName.ToString() ) );
            fields.Add( new Pair<string, string>( "jobRevision",	jobRevision.ToString() ) );
            fields.Add( new Pair<string, string>( "sublotID",	sublotID.ToString() ) );
            fields.Add( new Pair<string, string>( "operatorName",	operatorName.ToString() ) );
            fields.Add( new Pair<string, string>( "executiveType",	executiveType.ToString() ) );
            fields.Add( new Pair<string, string>( "executiveVersion",	executiveVersion.ToString() ) );
            fields.Add( new Pair<string, string>( "testCode",	testCode.ToString() ) );
            fields.Add( new Pair<string, string>( "testTemp",	testTemp.ToString() ) );
            fields.Add( new Pair<string, string>( "userText",	userText.ToString() ) );
            fields.Add( new Pair<string, string>( "auxFile",	auxFile.ToString() ) );
            fields.Add( new Pair<string, string>( "packageType",	packageType.ToString() ) );
            fields.Add( new Pair<string, string>( "familyID",	familyID.ToString() ) );
            fields.Add( new Pair<string, string>( "dateCode",	dateCode.ToString() ) );
            fields.Add( new Pair<string, string>( "facilityID",	facilityID.ToString() ) );
            fields.Add( new Pair<string, string>( "floorID",	floorID.ToString() ) );
            fields.Add( new Pair<string, string>( "processID",	processID.ToString() ) );
            fields.Add( new Pair<string, string>( "operatorFrequency",	operatorFrequency.ToString() ) );
            fields.Add( new Pair<string, string>( "specName",	specName.ToString() ) );
            fields.Add( new Pair<string, string>( "specVersion",	specVersion.ToString() ) );
            fields.Add( new Pair<string, string>( "flowID",	flowID.ToString() ) );
            fields.Add( new Pair<string, string>( "setupID",	setupID.ToString() ) );
            fields.Add( new Pair<string, string>( "designRevision",	designRevision.ToString() ) );
            fields.Add( new Pair<string, string>( "engineeringLotID",	engineeringLotID.ToString() ) );
            fields.Add( new Pair<string, string>( "romCode",	romCode.ToString() ) );
            fields.Add( new Pair<string, string>( "serialNumber",	serialNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "supervisorName",	supervisorName.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.MIR; }

        public U4 setupTime;
        public U4 startTime;
        public U1 stationNumber;
        public C1 modeCode;
        public C1 retestCode;
        public C1 protectionCode;
        public U2 burninTime;
        public C1 commandModeCode;
        public CN lotID;
        public CN partType;
        public CN nodeName;
        public CN testerType;
        public CN jobName;
        public CN jobRevision;
        public CN sublotID;
        public CN operatorName;
        public CN executiveType;
        public CN executiveVersion;
        public CN testCode;
        public CN testTemp;
        public CN userText;
        public CN auxFile;
        public CN packageType;
        public CN familyID;
        public CN dateCode;
        public CN facilityID;
        public CN floorID;
        public CN processID;
        public CN operatorFrequency;
        public CN specName;
        public CN specVersion;
        public CN flowID;
        public CN setupID;
        public CN designRevision;
        public CN engineeringLotID;
        public CN romCode;
        public CN serialNumber;
        public CN supervisorName;

    };




    public class MPRRecord : Record {
        public MPRRecord() {
            recordHeader = new RecordHeader(RecordType.MPR);
            testNumber = 0;
            headNumber = 0;
            siteNumber = 0;
            testFlag = 0;
            parmFlag = 0;
            rtnIcnt = 0;
            resultCount = 0;
            optFlag = 0;
            resultScale = 0;
            llmScale = 0;
            hlmScale = 0;
            loLimit = 0;
            hiLimit = 0;
            startIn = 0;
            incrIn = 0;
            loSpec = 0;
            hiSpec = 0;
            returnStates = new List<N1>();
            returnResults = new List<R4>();
            testText = new CN();
            alarmID = new CN();
            returnIndexes = new List<U2>();
            units = new CN();
            unitsIn = new CN();
            cResFmt = new CN();
            cLlmFmt = new CN();
            cHlmFmt = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 4; // U4 testNumber
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 1; // B1 testFlag
            len += 1; // B1 parmFlag
            len += 2; // U2 rtnIcnt
            len += 2; // U2 resultCount
            for(int i=0; i < returnStates.Count; i++) {
                len += 1; // N1 returnStates
            }
            for(int i=0; i < returnResults.Count; i++) {
                len += 4; // R4 returnResults
            }
            len += testText.getLength(); // CN testText
            len += alarmID.getLength(); // CN alarmID
            len += 1; // B1 optFlag
            len += 1; // I1 resultScale
            len += 1; // I1 llmScale
            len += 1; // I1 hlmScale
            len += 4; // R4 loLimit
            len += 4; // R4 hiLimit
            len += 4; // R4 startIn
            len += 4; // R4 incrIn
            for(int i=0; i < returnIndexes.Count; i++) {
                len += 2; // U2 returnIndexes
            }
            len += units.getLength(); // CN units
            len += unitsIn.getLength(); // CN unitsIn
            len += cResFmt.getLength(); // CN cResFmt
            len += cLlmFmt.getLength(); // CN cLlmFmt
            len += cHlmFmt.getLength(); // CN cHlmFmt
            len += 4; // R4 loSpec
            len += 4; // R4 hiSpec

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "testNumber",	testNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "testFlag",	testFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "parmFlag",	parmFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "rtnIcnt",	rtnIcnt.ToString() ) );
            fields.Add( new Pair<string, string>( "resultCount",	resultCount.ToString() ) );
            fields.Add( new Pair<string, string>( "returnStates",	returnStates.ToString() ) );
            fields.Add( new Pair<string, string>( "returnResults",	returnResults.ToString() ) );
            fields.Add( new Pair<string, string>( "testText",	testText.ToString() ) );
            fields.Add( new Pair<string, string>( "alarmID",	alarmID.ToString() ) );
            fields.Add( new Pair<string, string>( "optFlag",	optFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "resultScale",	resultScale.ToString() ) );
            fields.Add( new Pair<string, string>( "llmScale",	llmScale.ToString() ) );
            fields.Add( new Pair<string, string>( "hlmScale",	hlmScale.ToString() ) );
            fields.Add( new Pair<string, string>( "loLimit",	loLimit.ToString() ) );
            fields.Add( new Pair<string, string>( "hiLimit",	hiLimit.ToString() ) );
            fields.Add( new Pair<string, string>( "startIn",	startIn.ToString() ) );
            fields.Add( new Pair<string, string>( "incrIn",	incrIn.ToString() ) );
            fields.Add( new Pair<string, string>( "returnIndexes",	returnIndexes.ToString() ) );
            fields.Add( new Pair<string, string>( "units",	units.ToString() ) );
            fields.Add( new Pair<string, string>( "unitsIn",	unitsIn.ToString() ) );
            fields.Add( new Pair<string, string>( "cResFmt",	cResFmt.ToString() ) );
            fields.Add( new Pair<string, string>( "cLlmFmt",	cLlmFmt.ToString() ) );
            fields.Add( new Pair<string, string>( "cHlmFmt",	cHlmFmt.ToString() ) );
            fields.Add( new Pair<string, string>( "loSpec",	loSpec.ToString() ) );
            fields.Add( new Pair<string, string>( "hiSpec",	hiSpec.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.MPR; }

        public U4       testNumber;
        public U1       headNumber;
        public U1       siteNumber;
        public B1       testFlag;
        public B1       parmFlag;
        public U2       rtnIcnt;
        public U2       resultCount;
        public List<N1> returnStates;
        public List<R4> returnResults;
        public CN       testText;
        public CN       alarmID;
        public B1       optFlag;
        public I1       resultScale;
        public I1       llmScale;
        public I1       hlmScale;
        public R4       loLimit;
        public R4       hiLimit;
        public R4       startIn;
        public R4       incrIn;
        public List<U2> returnIndexes;
        public CN       units;
        public CN       unitsIn;
        public CN       cResFmt;
        public CN       cLlmFmt;
        public CN       cHlmFmt;
        public R4       loSpec;
        public R4       hiSpec;

    };




    public class MRRRecord : Record {
        public MRRRecord() {
            recordHeader = new RecordHeader(RecordType.MRR);
            finishTime = 0;
            dispositionCode = ' ';
            userLotDescription = new CN();
            executiveLotDescription = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 4; // U4 finishTime
            len += 1; // C1 dispositionCode
            len += userLotDescription.getLength(); // CN userLotDescription
            len += executiveLotDescription.getLength(); // CN executiveLotDescription

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "finishTime",	finishTime.ToString() ) );
            fields.Add( new Pair<string, string>( "dispositionCode",	dispositionCode.ToString() ) );
            fields.Add( new Pair<string, string>( "userLotDescription",	userLotDescription.ToString() ) );
            fields.Add( new Pair<string, string>( "executiveLotDescription",	executiveLotDescription.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.MRR; }

        public U4 finishTime;
        public C1 dispositionCode;
        public CN userLotDescription;
        public CN executiveLotDescription;

    };




    public class PCRRecord : Record {
        public PCRRecord() {
            recordHeader = new RecordHeader(RecordType.PCR);
            headNumber = 0;
            siteNumber = 0;
            partCount = 0;
            retestCount = 4294967295U;
            abortCount = 4294967295U;
            goodCount = 4294967295U;
            funcCount = 4294967295U;

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 4; // U4 partCount
            len += 4; // U4 retestCount
            len += 4; // U4 abortCount
            len += 4; // U4 goodCount
            len += 4; // U4 funcCount

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "partCount",	partCount.ToString() ) );
            fields.Add( new Pair<string, string>( "retestCount",	retestCount.ToString() ) );
            fields.Add( new Pair<string, string>( "abortCount",	abortCount.ToString() ) );
            fields.Add( new Pair<string, string>( "goodCount",	goodCount.ToString() ) );
            fields.Add( new Pair<string, string>( "funcCount",	funcCount.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.PCR; }

        public U1 headNumber;
        public U1 siteNumber;
        public U4 partCount;
        public U4 retestCount;
        public U4 abortCount;
        public U4 goodCount;
        public U4 funcCount;

    };




    public class PGRRecord : Record {
        public PGRRecord() {
            recordHeader = new RecordHeader(RecordType.PGR);
            groupIndex = 0;
            indexCount = 0;
            groupName = new CN();
            pmrIndex = new List<U2>();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 2; // U2 groupIndex
            len += groupName.getLength(); // CN groupName
            len += 2; // U2 indexCount
            for(int i=0; i < pmrIndex.Count; i++) {
                len += 2; // U2 pmrIndex
            }

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "groupIndex",	groupIndex.ToString() ) );
            fields.Add( new Pair<string, string>( "groupName",	groupName.ToString() ) );
            fields.Add( new Pair<string, string>( "indexCount",	indexCount.ToString() ) );
            fields.Add( new Pair<string, string>( "pmrIndex",	pmrIndex.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.PGR; }

        public U2 groupIndex;
        public CN groupName;
        public U2 indexCount;
        public List<U2> pmrIndex;

    };




    public class PIRRecord : Record {
        public PIRRecord() {
            recordHeader = new RecordHeader(RecordType.PIR);
            headNumber = 0;
            siteNumber = 0;

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.PIR; }

        public U1 headNumber;
        public U1 siteNumber;

    };




    public class PLRRecord : Record {
        public PLRRecord() {
            recordHeader     = new RecordHeader(RecordType.PLR);
            groupCount       = 0;
            groupIndex       = new List<U2>();
            groupMode        = new List<U2>();
            groupRadix       = new List<U1>();
            programCharRight = new List<CN>();
            programCharLeft  = new List<CN>();
            returnCharLeft   = new List<CN>();
            returnCharRight   = new List<CN>();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 2; // U2 groupCount
            for(int i=0; i < groupIndex.Count; i++) {
                len += 2; // U2 groupIndex
            }
            for(int i=0; i < groupMode.Count; i++) {
                len += 2; // U2 groupMode
            }
            for(int i=0; i < groupRadix.Count; i++) {
                len += 1; // U1 groupRadix
            }
            for(int i=0; i < programCharRight.Count; i++) {
                len += programCharRight[i].getLength(); // CN programCharRight
            }
            for(int i=0; i < returnCharRight.Count; i++) {
                len += returnCharRight[i].getLength(); // CN returnCharRight
            }
            for(int i=0; i < programCharLeft.Count; i++) {
                len += programCharLeft[i].getLength(); // CN programCharLeft
            }
            for(int i=0; i < returnCharLeft.Count; i++) {
                len += returnCharLeft[i].getLength(); // CN returnCharLeft
            }

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "groupCount",	groupCount.ToString() ) );
            fields.Add( new Pair<string, string>( "groupIndex",	groupIndex.ToString() ) );
            fields.Add( new Pair<string, string>( "groupMode",	groupMode.ToString() ) );
            fields.Add( new Pair<string, string>( "groupRadix",	groupRadix.ToString() ) );
            fields.Add( new Pair<string, string>( "programCharRight",	programCharRight.ToString() ) );
            fields.Add( new Pair<string, string>( "returnCharRight",	returnCharRight.ToString() ) );
            fields.Add( new Pair<string, string>( "programCharLeft",	programCharLeft.ToString() ) );
            fields.Add( new Pair<string, string>( "returnCharLeft",	returnCharLeft.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.PLR; }

        public U2       groupCount;
        public List<U2> groupIndex;
        public List<U2> groupMode;
        public List<U1> groupRadix;
        public List<CN> programCharRight;
        public List<CN> returnCharRight;
        public List<CN> programCharLeft;
        public List<CN> returnCharLeft;

    };




    public class PMRRecord : Record {
        public PMRRecord() {
            recordHeader = new RecordHeader(RecordType.PMR);
            pmrIndex = 0;
            channelType = 0;
            headNumber = 0;
            siteNumber = 0;
            channelName = new CN();
            physicalName = new CN();
            logicalName = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 2; // U2 pmrIndex
            len += 2; // U2 channelType
            len += channelName.getLength(); // CN channelName
            len += physicalName.getLength(); // CN physicalName
            len += logicalName.getLength(); // CN logicalName
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "pmrIndex",	pmrIndex.ToString() ) );
            fields.Add( new Pair<string, string>( "channelType",	channelType.ToString() ) );
            fields.Add( new Pair<string, string>( "channelName",	channelName.ToString() ) );
            fields.Add( new Pair<string, string>( "physicalName",	physicalName.ToString() ) );
            fields.Add( new Pair<string, string>( "logicalName",	logicalName.ToString() ) );
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.PMR; }

        public U2 pmrIndex;
        public U2 channelType;
        public CN channelName;
        public CN physicalName;
        public CN logicalName;
        public U1 headNumber;
        public U1 siteNumber;

    };




    public class PRRRecord : Record {
        public PRRRecord() {
            recordHeader = new RecordHeader(RecordType.PRR);
            headNumber = 0;
            siteNumber = 0;
            partFlag = 0;
            numTests = 0;
            hardBin = 0;
            softBin = 0;
            xCoord = 0;
            yCoord = 0;
            testTime = 0;
            partID = new CN();
            partText = new CN();
            partFix = new BN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 1; // B1 partFlag
            len += 2; // U2 numTests
            len += 2; // U2 hardBin
            len += 2; // U2 softBin
            len += 2; // I2 xCoord
            len += 2; // I2 yCoord
            len += 4; // U4 testTime
            len += partID.getLength(); // CN partID
            len += partText.getLength(); // CN partText
            len += partFix.getLength(); // BN partFix

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "partFlag",	partFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "numTests",	numTests.ToString() ) );
            fields.Add( new Pair<string, string>( "hardBin",	hardBin.ToString() ) );
            fields.Add( new Pair<string, string>( "softBin",	softBin.ToString() ) );
            fields.Add( new Pair<string, string>( "xCoord",	xCoord.ToString() ) );
            fields.Add( new Pair<string, string>( "yCoord",	yCoord.ToString() ) );
            fields.Add( new Pair<string, string>( "testTime",	testTime.ToString() ) );
            fields.Add( new Pair<string, string>( "partID",	partID.ToString() ) );
            fields.Add( new Pair<string, string>( "partText",	partText.ToString() ) );
            fields.Add( new Pair<string, string>( "partFix",	partFix.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.PRR; }

        public U1 headNumber;
        public U1 siteNumber;
        public B1 partFlag;
        public U2 numTests;
        public U2 hardBin;
        public U2 softBin;
        public I2 xCoord;
        public I2 yCoord;
        public U4 testTime;
        public CN partID;
        public CN partText;
        public BN partFix;

    };




    public class PTRRecord : Record {
        public PTRRecord() {
            recordHeader = new RecordHeader(RecordType.PTR);
            testNumber = 0;
            headNumber = 0;
            siteNumber = 0;
            testFlag = 0;
            parmFlag = 0;
            testResult = 0;
            optFlag = 0;
            resultScale = 0;
            llmScale = 0;
            hlmScale = 0;
            loLimit = 0;
            hiLimit = 0;
            loSpec = 0;
            hiSpec = 0;
            testText = new CN();
            alarmID = new CN();
            units = new CN();
            cResFmt = new CN();
            cLlmFmt = new CN();
            cHlmFmt = new CN();

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 4; // U4 testNumber
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 1; // B1 testFlag
            len += 1; // B1 parmFlag
            len += 4; // R4 testResult
            len += testText.getLength(); // CN testText
            len += alarmID.getLength(); // CN alarmID
            len += 1; // B1 optFlag
            len += 1; // I1 resultScale
            len += 1; // I1 llmScale
            len += 1; // I1 hlmScale
            len += 4; // R4 loLimit
            len += 4; // R4 hiLimit
            len += units.getLength(); // CN units
            len += cResFmt.getLength(); // CN cResFmt
            len += cLlmFmt.getLength(); // CN cLlmFmt
            len += cHlmFmt.getLength(); // CN cHlmFmt
            len += 4; // R4 loSpec
            len += 4; // R4 hiSpec

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "testNumber",	testNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "testFlag",	testFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "parmFlag",	parmFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "testResult",	testResult.ToString() ) );
            fields.Add( new Pair<string, string>( "testText",	testText.ToString() ) );
            fields.Add( new Pair<string, string>( "alarmID",	alarmID.ToString() ) );
            fields.Add( new Pair<string, string>( "optFlag",	optFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "resultScale",	resultScale.ToString() ) );
            fields.Add( new Pair<string, string>( "llmScale",	llmScale.ToString() ) );
            fields.Add( new Pair<string, string>( "hlmScale",	hlmScale.ToString() ) );
            fields.Add( new Pair<string, string>( "loLimit",	loLimit.ToString() ) );
            fields.Add( new Pair<string, string>( "hiLimit",	hiLimit.ToString() ) );
            fields.Add( new Pair<string, string>( "units",	units.ToString() ) );
            fields.Add( new Pair<string, string>( "cResFmt",	cResFmt.ToString() ) );
            fields.Add( new Pair<string, string>( "cLlmFmt",	cLlmFmt.ToString() ) );
            fields.Add( new Pair<string, string>( "cHlmFmt",	cHlmFmt.ToString() ) );
            fields.Add( new Pair<string, string>( "loSpec",	loSpec.ToString() ) );
            fields.Add( new Pair<string, string>( "hiSpec",	hiSpec.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.PTR; }

        //
        // optFlag decoding
        //
        public bool isResultScaleInValid () { return ((optFlag & 0x01) > 0); }
        public bool isLoSpecInvalid      () { return ((optFlag & 0x04) > 0); }
        public bool isHiSpecInvalid      () { return ((optFlag * 0x08) > 0); }
        public bool isLoLimitInvalid     () { return ((optFlag & 0x10) > 0); }
        public bool isHiLimitInvalid     () { return ((optFlag & 0x20) > 0); }
        //public bool 
            //
            // testFlag decoding
            //
            public bool isAlarm        () { return  ((testFlag & 0x01) > 0); }
            public bool isResultValid  () { return !((testFlag & 0x02) > 0); }
            public bool isTestReliable () { return !((testFlag & 0x04) > 0); }
            public bool isTimeout      () { return  ((testFlag & 0x08) > 0); }
            public bool isTestExecuted () { return  ((testFlag & 0x10) > 0); }
            public bool isTestAborted  () { return  ((testFlag & 0x20) > 0); }
            public bool isPFValid      () { return !((testFlag & 0x40) > 0); }
            public bool isTestPass     () { return !((testFlag & 0x80) > 0); }
            //
            // parmFlag decoding
            //
            public bool isScaleError   () { return  ((parmFlag & 0x01) > 0); }
            public bool isDriftError   () { return  ((parmFlag & 0x02) > 0); }
            public bool isOscillatior  () { return  ((parmFlag & 0x04) > 0); }
            public bool isMeasHi       () { return  ((parmFlag & 0x08) > 0); }
            public bool isMeasLo       () { return  ((parmFlag & 0x10) > 0); }
            public bool isLoLimitPass  () { return  ((parmFlag & 0x40) > 0); }
            public bool isHiLimitPass  () { return  ((parmFlag & 0x80) > 0); }

            public bool considerResult () { return  !(((testFlag & 0x03F) | (parmFlag & 0x07)) > 0); }
            public bool considerResultWithoutAlarm() { return !(((testFlag & 0x03E) | (parmFlag & 0x07)) > 0); }

        public U4 testNumber;
        public U1 headNumber;
        public U1 siteNumber;
        public B1 testFlag;
        public B1 parmFlag;
        public R4 testResult;
        public CN testText;
        public CN alarmID;
        public B1 optFlag;
        public I1 resultScale;
        public I1 llmScale;
        public I1 hlmScale;
        public R4 loLimit;
        public R4 hiLimit;
        public CN units;
        public CN cResFmt;
        public CN cLlmFmt;
        public CN cHlmFmt;
        public R4 loSpec;
        public R4 hiSpec;

    };




    public class RDRRecord : Record {
        public RDRRecord() {
            recordHeader = new RecordHeader(RecordType.RDR);
            numBins = 0;
            retestbinNumbers = new List<U2>();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 2; // U2 numBins
            for(int i=0; i < retestbinNumbers.Count; i++) {
                len += 2; // U2 retestbinNumbers
            }

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "numBins",	numBins.ToString() ) );
            fields.Add( new Pair<string, string>( "retestbinNumbers",	retestbinNumbers.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.RDR; }

        public U2 numBins;
        public List<U2> retestbinNumbers;

    };




    public class SBRRecord : Record {
        public SBRRecord() {
            recordHeader = new RecordHeader(RecordType.SBR);
            headNumber = 0;
            siteNumber = 0;
            sbinNumber = 0;
            sbinCount = 0;
            sbinPF = ' ';
            sbinName = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 2; // U2 sbinNumber
            len += 4; // U4 sbinCount
            len += 1; // C1 sbinPF
            len += sbinName.getLength(); // CN sbinName

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "sbinNumber",	sbinNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "sbinCount",	sbinCount.ToString() ) );
            fields.Add( new Pair<string, string>( "sbinPF",	sbinPF.ToString() ) );
            fields.Add( new Pair<string, string>( "sbinName",	sbinName.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.SBR; }

        public U1 headNumber;
        public U1 siteNumber;
        public U2 sbinNumber;
        public U4 sbinCount;
        public C1 sbinPF;
        public CN sbinName;

    };

    public class SDRRecord : Record {
        public SDRRecord() {
            recordHeader = new RecordHeader(RecordType.SDR);
            headNumber = 0;
            siteGroup = 0;
            siteCount = 0;
            siteNumbers = new List<U1>();
            handlerType = new CN();
            handlerID = new CN();
            probeCardType = new CN();
            probeCardID = new CN();
            loadBoardType = new CN();
            loadBoardID = new CN();
            dibType = new CN();
            dibID = new CN();
            cableType = new CN();
            cableID = new CN();
            contactorType = new CN();
            contactorID = new CN();
            laserType = new CN();
            laserID = new CN();
            extraType = new CN();
            extraID = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteGroup
            len += 1; // U1 siteCount
            for(int i=0; i < siteNumbers.Count; i++) {
                len += 1; // U1 siteNumbers
            }
            len += handlerType.getLength(); // CN handlerType
            len += handlerID.getLength(); // CN handlerID
            len += probeCardType.getLength(); // CN probeCardType
            len += probeCardID.getLength(); // CN probeCardID
            len += loadBoardType.getLength(); // CN loadBoardType
            len += loadBoardID.getLength(); // CN loadBoardID
            len += dibType.getLength(); // CN dibType
            len += dibID.getLength(); // CN dibID
            len += cableType.getLength(); // CN cableType
            len += cableID.getLength(); // CN cableID
            len += contactorType.getLength(); // CN contactorType
            len += contactorID.getLength(); // CN contactorID
            len += laserType.getLength(); // CN laserType
            len += laserID.getLength(); // CN laserID
            len += extraType.getLength(); // CN extraType
            len += extraID.getLength(); // CN extraID

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteGroup",	siteGroup.ToString() ) );
            fields.Add( new Pair<string, string>( "siteCount",	siteCount.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumbers",	siteNumbers.ToString() ) );
            fields.Add( new Pair<string, string>( "handlerType",	handlerType.ToString() ) );
            fields.Add( new Pair<string, string>( "handlerID",	handlerID.ToString() ) );
            fields.Add( new Pair<string, string>( "probeCardType",	probeCardType.ToString() ) );
            fields.Add( new Pair<string, string>( "probeCardID",	probeCardID.ToString() ) );
            fields.Add( new Pair<string, string>( "loadBoardType",	loadBoardType.ToString() ) );
            fields.Add( new Pair<string, string>( "loadBoardID",	loadBoardID.ToString() ) );
            fields.Add( new Pair<string, string>( "dibType",	dibType.ToString() ) );
            fields.Add( new Pair<string, string>( "dibID",	dibID.ToString() ) );
            fields.Add( new Pair<string, string>( "cableType",	cableType.ToString() ) );
            fields.Add( new Pair<string, string>( "cableID",	cableID.ToString() ) );
            fields.Add( new Pair<string, string>( "contactorType",	contactorType.ToString() ) );
            fields.Add( new Pair<string, string>( "contactorID",	contactorID.ToString() ) );
            fields.Add( new Pair<string, string>( "laserType",	laserType.ToString() ) );
            fields.Add( new Pair<string, string>( "laserID",	laserID.ToString() ) );
            fields.Add( new Pair<string, string>( "extraType",	extraType.ToString() ) );
            fields.Add( new Pair<string, string>( "extraID",	extraID.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.SDR; }

        public U1 headNumber;
        public U1 siteGroup;
        public U1 siteCount;
        public List<U1> siteNumbers;
        public CN handlerType;
        public CN handlerID;
        public CN probeCardType;
        public CN probeCardID;
        public CN loadBoardType;
        public CN loadBoardID;
        public CN dibType;
        public CN dibID;
        public CN cableType;
        public CN cableID;
        public CN contactorType;
        public CN contactorID;
        public CN laserType;
        public CN laserID;
        public CN extraType;
        public CN extraID;

    };




    public class TSRRecord : Record {
        public TSRRecord() {
            recordHeader = new RecordHeader(RecordType.TSR);
            headNumber = 0;
            siteNumber = 0;
            testType = ' ';
            testNumber = 0;
            execCount = 0;
            failCount = 0;
            alarmCount = 0;
            optFlag = 0;
            testTime = 0;
            testMin = 0;
            testMax = 0;
            testSums = 0;
            testSquares = 0;
            testName = new CN();
            sequencerName = new CN();
            testLabel = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteNumber
            len += 1; // C1 testType
            len += 4; // U4 testNumber
            len += 4; // U4 execCount
            len += 4; // U4 failCount
            len += 4; // U4 alarmCount
            len += testName.getLength(); // CN testName
            len += sequencerName.getLength(); // CN sequencerName
            len += testLabel.getLength(); // CN testLabel
            len += 1; // B1 optFlag
            len += 4; // R4 testTime
            len += 4; // R4 testMin
            len += 4; // R4 testMax
            len += 4; // R4 testSums
            len += 4; // R4 testSquares

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteNumber",	siteNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "testType",	testType.ToString() ) );
            fields.Add( new Pair<string, string>( "testNumber",	testNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "execCount",	execCount.ToString() ) );
            fields.Add( new Pair<string, string>( "failCount",	failCount.ToString() ) );
            fields.Add( new Pair<string, string>( "alarmCount",	alarmCount.ToString() ) );
            fields.Add( new Pair<string, string>( "testName",	testName.ToString() ) );
            fields.Add( new Pair<string, string>( "sequencerName",	sequencerName.ToString() ) );
            fields.Add( new Pair<string, string>( "testLabel",	testLabel.ToString() ) );
            fields.Add( new Pair<string, string>( "optFlag",	optFlag.ToString() ) );
            fields.Add( new Pair<string, string>( "testTime",	testTime.ToString() ) );
            fields.Add( new Pair<string, string>( "testMin",	testMin.ToString() ) );
            fields.Add( new Pair<string, string>( "testMax",	testMax.ToString() ) );
            fields.Add( new Pair<string, string>( "testSums",	testSums.ToString() ) );
            fields.Add( new Pair<string, string>( "testSquares",	testSquares.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.TSR; }

        public U1 headNumber;
        public U1 siteNumber;
        public C1 testType;
        public U4 testNumber;
        public U4 execCount;
        public U4 failCount;
        public U4 alarmCount;
        public CN testName;
        public CN sequencerName;
        public CN testLabel;
        public B1 optFlag;
        public R4 testTime;
        public R4 testMin;
        public R4 testMax;
        public R4 testSums;
        public R4 testSquares;

    };

    public class WCRRecord : Record {
        public WCRRecord() {
            recordHeader = new RecordHeader(RecordType.WCR);
            waferSize    = 0;
            dieHeight    = 0;
            dieWidth     = 0;
            waferUnits   = 0;
            waferFlat    = ' ';
            centerX      = 0;
            centerY      = 0;
            positiveX    = ' ';
            positiveY    = ' ';

        }
        public override U2 getLength() {
            U2 len = 0;
            len += 4; // R4 waferSize
            len += 4; // R4 dieHeight
            len += 4; // R4 dieWidth
            len += 1; // U1 waferUnits
            len += 1; // C1 waferFlat
            len += 2; // I2 centerX
            len += 2; // I2 centerY
            len += 1; // C1 positiveX
            len += 1; // C1 positiveY

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "waferSize",	waferSize.ToString() ) );
            fields.Add( new Pair<string, string>( "dieHeight",	dieHeight.ToString() ) );
            fields.Add( new Pair<string, string>( "dieWidth",	dieWidth.ToString() ) );
            fields.Add( new Pair<string, string>( "waferUnits",	waferUnits.ToString() ) );
            fields.Add( new Pair<string, string>( "waferFlat",	waferFlat.ToString() ) );
            fields.Add( new Pair<string, string>( "centerX",	centerX.ToString() ) );
            fields.Add( new Pair<string, string>( "centerY",	centerY.ToString() ) );
            fields.Add( new Pair<string, string>( "positiveX",	positiveX.ToString() ) );
            fields.Add( new Pair<string, string>( "positiveY",	positiveY.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.WCR; }

        public R4 waferSize;
        public R4 dieHeight;
        public R4 dieWidth;
        public U1 waferUnits;
        public C1 waferFlat;
        public I2 centerX;
        public I2 centerY;
        public C1 positiveX;
        public C1 positiveY;
    };

    public class WIRRecord : Record {
        public WIRRecord() {
            recordHeader = new RecordHeader(RecordType.WIR);
            headNumber = 0;
            siteGroup = 0;
            startTime = 0;
            waferID = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteGroup
            len += 4; // U4 startTime
            len += waferID.getLength(); // CN waferID

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteGroup",	siteGroup.ToString() ) );
            fields.Add( new Pair<string, string>( "startTime",	startTime.ToString() ) );
            fields.Add( new Pair<string, string>( "waferID",	waferID.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.WIR; }

        public U1 headNumber;
        public U1 siteGroup;
        public U4 startTime;
        public CN waferID;

    };




    public class WRRRecord : Record {
        public WRRRecord() {
            recordHeader = new RecordHeader(RecordType.WRR);
            headNumber = 0;
            siteGroup = 0;
            finishTime = 0;
            partCount = 0;
            retestCount = 0;
            abortCount = 0;
            goodCount = 0;
            funcCount = 0;
            waferID = new CN();
            fabWaferID = new CN();
            waferFrameID = new CN();
            waferMaskID =  new CN();
            userDescription = new CN();
            execDescription = new CN();
        }
        public override U2 getLength() {
            U2 len = 0;
            len += 1; // U1 headNumber
            len += 1; // U1 siteGroup
            len += 4; // U4 finishTime
            len += 4; // U4 partCount
            len += 4; // U4 retestCount
            len += 4; // U4 abortCount
            len += 4; // U4 goodCount
            len += 4; // U4 funcCount
            len += waferID.getLength(); // CN waferID
            len += fabWaferID.getLength(); // CN fabWaferID
            len += waferFrameID.getLength(); // CN waferFrameID
            len += waferMaskID.getLength(); // CN waferMaskID
            len += userDescription.getLength(); // CN userDescription
            len += execDescription.getLength(); // CN execDescription

            return len;
        }
        public override void getFields( ref List< Pair<string, string> > fields) {
            fields.Add( new Pair<string, string>( "headNumber",	headNumber.ToString() ) );
            fields.Add( new Pair<string, string>( "siteGroup",	siteGroup.ToString() ) );
            fields.Add( new Pair<string, string>( "finishTime",	finishTime.ToString() ) );
            fields.Add( new Pair<string, string>( "partCount",	partCount.ToString() ) );
            fields.Add( new Pair<string, string>( "retestCount",	retestCount.ToString() ) );
            fields.Add( new Pair<string, string>( "abortCount",	abortCount.ToString() ) );
            fields.Add( new Pair<string, string>( "goodCount",	goodCount.ToString() ) );
            fields.Add( new Pair<string, string>( "funcCount",	funcCount.ToString() ) );
            fields.Add( new Pair<string, string>( "waferID",	waferID.ToString() ) );
            fields.Add( new Pair<string, string>( "fabWaferID",	fabWaferID.ToString() ) );
            fields.Add( new Pair<string, string>( "waferFrameID",	waferFrameID.ToString() ) );
            fields.Add( new Pair<string, string>( "waferMaskID",	waferMaskID.ToString() ) );
            fields.Add( new Pair<string, string>( "userDescription",	userDescription.ToString() ) );
            fields.Add( new Pair<string, string>( "execDescription",	execDescription.ToString() ) );

        }
        public override RecordType getRecordType() { return RecordType.WRR; }

        public U1 headNumber;
        public U1 siteGroup;
        public U4 finishTime;
        public U4 partCount;
        public U4 retestCount;
        public U4 abortCount;
        public U4 goodCount;
        public U4 funcCount;
        public CN waferID;
        public CN fabWaferID;
        public CN waferFrameID;
        public CN waferMaskID;
        public CN userDescription;
        public CN execDescription;

    };




}

